package com.bottomlord.microprofile.rest;

import com.bottomlord.microprofile.rest.annotation.AnnotatedParamMetadata;

import javax.ws.rs.*;
import java.lang.annotation.Annotation;
import java.util.*;

import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static java.util.Collections.unmodifiableSet;

/**
 * @author ChenYue
 * @date 2021/4/20 16:06
 */
public class RequestTemplate {
    public static Set<Class<? extends Annotation>> SUPPORTED_PARAM_ANNOTATION_TYPES = unmodifiableSet(new LinkedHashSet<>(asList(
        PathParam.class,
        QueryParam.class,
        MatrixParam.class,
        FormParam.class,
        CookieParam.class,
        HeaderParam.class
    )));

    private String method;

    private String uriTemplate;

    private final Map<Class<? extends Annotation>, List<AnnotatedParamMetadata>> annotatedParamMetadataMap = new HashMap<>();

    private final Set<String> consumes = new LinkedHashSet<>();

    private final Set<String> produces = new LinkedHashSet<>();

    public RequestTemplate method(String method) {
        this.method = method;
        return this;
    }

    public RequestTemplate urlTemplate(String uriTemplate) {
        this.uriTemplate = uriTemplate;
        return this;
    }

    public RequestTemplate annotatedParamMetadata(List<AnnotatedParamMetadata> annotatedParamMetadatas) {
        annotatedParamMetadatas.forEach(this::annotatedParamMetadata);
        return this;
    }

    public RequestTemplate annotatedParamMetadata(AnnotatedParamMetadata... annotatedParamMetadatas) {
        Arrays.stream(annotatedParamMetadatas).forEach(this::annotatedParamMetadata);
        return this;
    }

    public RequestTemplate annotatedParamMetadata(AnnotatedParamMetadata annotatedParamMetadata) {
        Class<? extends Annotation> annotationType = annotatedParamMetadata.getAnnotationType();
        List<AnnotatedParamMetadata> metadataList = annotatedParamMetadataMap.computeIfAbsent(annotationType, type -> new LinkedList<>());
        metadataList.add(annotatedParamMetadata);
        return this;
    }

    public RequestTemplate consumes(String... consumes) {
        this.consumes.addAll(asList(consumes));
        return this;
    }

    public RequestTemplate produces(String... produces) {
        this.produces.addAll(asList(produces));
        return this;
    }

    public List<AnnotatedParamMetadata> getAnnotatedParamMetadata(Class<? extends Annotation> annotationType) {
        return annotatedParamMetadataMap.getOrDefault(annotationType, emptyList());
    }

    public String getMethod() {
        return method;
    }

    public String getUriTemplate() {
        return uriTemplate;
    }

    public Set<String> getConsumes() {
        return unmodifiableSet(consumes);
    }

    public Set<String> getProduces() {
        return unmodifiableSet(produces);
    }
}
